#include "stdafx.h"
#include "Core/Commons.h"
#include "UIAnimPlayer.h"
#include "Core/DEF.h"

UIAnimPlayer::UIAnimPlayer(bool DataByFrame)
{
	m_isDataByFrame = DataByFrame;

	m_playAnim = UI_ANIMATION::AnimEnter;
	for(int i=0;i<UI_ANIMATION::AnimCount; ++i)
	{
		m_anims[i] = NULL;
	}
	m_finish.reset();
}

UIAnimPlayer::~UIAnimPlayer()
{
	for(int i=0;i<UI_ANIMATION::AnimCount; ++i)
	{
		m_anims[i] = NULL;
	}
}

bool UIAnimPlayer::IsAnimEnd(UI_ANIMATION::ANIM_ENUM animFlag)
{
	if(m_anims[animFlag])
	{
		if( m_playAnim == animFlag )
		{
			return !m_finish[animFlag];
		}
		else
		{
			return false;
		}
	}
	return true;
}

void UIAnimPlayer::PlayAnim(UI_ANIMATION::ANIM_ENUM animFlag)
{
	//if( m_finish[animFlag] )
	//{
	//	return;
	//}

	if(m_anims[animFlag])
	{
		m_time =0.0f;
		m_playAnim = animFlag;
		m_finish.set(animFlag);
	}
}

void UIAnimPlayer::AddAnim( UI_ANIMATION::ANIM_ENUM animIndex, UIAnim*p)
{
	m_anims[animIndex]  = p;
}

void UIAnimPlayer::Update(float df)
{
	if( m_anims[m_playAnim] == NULL )
	{
		return;
	}

	float maxRange = m_anims[m_playAnim]->m_timeRange;
	if( m_isDataByFrame )
	{
		maxRange = maxRange * DEF::FIXXED_UPDATE_TIME;
	}
	if(m_time > maxRange  )
	{
		if( m_anims[m_playAnim]->m_isLoop )
		{
			m_time = 0.0f;
		}
		else
		{
			m_finish.set(m_playAnim, false);
		}
		return;
	}

	m_time += df;
}

bool UIAnimPlayer::GetChannelData( UI_ANIMATION::CHANNEL_TYPE type, int targetIndex , UIAnimChannelData &result)
{	
	UIAnim* pAnim = m_anims[m_playAnim];
	if( pAnim == NULL )
	{
		return false;
	}
	int nIndex = -1;
	for(int i=0;i<pAnim->m_channels.size();++i)
	{
		UIChannel *pChannel = pAnim->m_channels[i];
		if( (pChannel->m_type == type) && ( pChannel->m_targetIndex == targetIndex ) )
		{
			nIndex  = i;
			break;
		}
	}

	if( nIndex == -1 )
	{
		return false;
	}

	UIChannel *pChannel = pAnim->m_channels[nIndex];

	for(int i=0;i<UI_ANIMATION::TimelineCount;++i)
	{
		UITimeline *pTimeline = pChannel->m_timelines[i];
		if( pTimeline == NULL )
		{
			result.m_values[i] = GetDefaultValue(i);
			continue;
		}

		float maxRange = m_anims[m_playAnim]->m_timeRange;
		if( m_isDataByFrame )
		{
			maxRange = maxRange *  DEF::FIXXED_UPDATE_TIME;
		}

		if( m_time > maxRange )
		{
			UIAnimKey pLastKey = pTimeline->m_keys[pTimeline->m_keys.size() - 1];
			result.m_values[i] = pLastKey.m_value;
			continue;
		}

		for(int j=0; j <pTimeline->m_keys.size() ;++j)
		{
			UIAnimKey pKey = pTimeline->m_keys[j];

			float KeyTime = pKey.m_keyTime;
			if( m_isDataByFrame )
			{
				KeyTime = KeyTime * DEF::FIXXED_UPDATE_TIME;
			}
			if( m_time < KeyTime )
			{
				if(  (j == 0) && (pKey.m_keyTime !=0) )
				{
					result.m_values[i] = pKey.m_value;
				}
				else
				{
					if( j!= 0)
					{
						UIAnimKey pPrevKey = pTimeline->m_keys[j-1];
						float PrevKeyTime = pPrevKey.m_keyTime;
						if( m_isDataByFrame )
						{
							PrevKeyTime = PrevKeyTime * DEF::FIXXED_UPDATE_TIME;
						}
						result.m_values[i] = ComputeInterpolation( PrevKeyTime, 
							pPrevKey.m_value, 
							KeyTime,
							pKey.m_value ,
							m_time);
					}
					else
					{
						ASSERT(0);
					}
				}
				break;
			}
			else if( m_time == KeyTime )
			{
				result.m_values[i] = pKey.m_value;
				break;
			}
			else if( m_time > KeyTime )
			{
				//skip
			}
		}
	}
	return true;
}

float UIAnimPlayer::GetDefaultValue(int style)
{
	switch(style )
	{
	case UI_ANIMATION::TimelinePositionX :
	case UI_ANIMATION::TimelinePositionY :
	case UI_ANIMATION::TimelineRotationZ:
		return 0.0f;
	case UI_ANIMATION::TimelineScale:
	case UI_ANIMATION::TimelineAlpha:
		return 1.0f;
	default:
		return 0.0f;
	}
}

float UIAnimPlayer::ComputeInterpolation( float time1, float value1, float time2, float value2, float curtime, UI_ANIMATION::InterpolationStyle style)
{
	switch( style )
	{
	case UI_ANIMATION::InterpolationLinear:
	default:
		return ComputeLinearResult( time1, value1, time2, value2, curtime);
	}
}

float UIAnimPlayer::ComputeLinearResult( float time1, float value1, float time2, float value2, float curtime )
{
	float length = time2 - time1;
	float valueSize = value2 - value1;
	float partLen = curtime - time1;
	float partSize = partLen * valueSize / length;
	float result = partSize + value1;

	return result;
}


bool UIAnimPlayer::HasAnim( UI_ANIMATION::ANIM_ENUM animFlag)
{
	if( m_anims[ animFlag ] )
	{
		return true;
	}
	return false;
}

void UIAnimPlayer::Reset()
{
	m_playAnim = UI_ANIMATION::AnimEnter;
	m_finish.reset();
}

float UIAnimPlayer::GetCurrentTime()
{
	return m_time;
}
